﻿using CardPhotoQCServer.QC;
using ComLib.ComType;
using LogLib;
using PipeClient;
using ProcessConfig;
using ProcessConfig.ConfigType;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace CardQCProcessor
{
    class Program
    {
        private static bool _bInitQCLib = false;

        public delegate bool ControlCtrlDelegate(int CtrlType);

        protected static IntPtr ParentFormHandle = IntPtr.Zero;
        /// <summary>
        /// 指示是否已经通知主窗体加载完成
        /// </summary>
        protected static bool _bNotified = false;

        public static string AppName = Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);

        private static QCProductFactory QCFactory = QCProductFactory.Instance;

        private static CardPhotoQCServer _server = null;

        private static QCProcess _processor = null;

        static void Main(string[] args)
        {
            if (args.Length > 0)
            {
                string arg = args[0];
                if (!string.IsNullOrEmpty(arg))
                {
                    ParentFormHandle = (IntPtr)Int32.Parse(arg);
                }
            }

            string fileName = Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
            Console.Title = fileName;
            IntPtr ParenthWnd = new IntPtr(0);
            IntPtr et = new IntPtr(0);
            ParenthWnd = FindWindow(null, fileName);
            //隐藏本dos窗体, 0: 后台执行；1:正常启动；2:最小化到任务栏；3:最大化 
            ShowWindow(ParenthWnd, 2);
            bool bRet = SetConsoleCtrlHandler(newDelegate, true);

            LoadConfig();
            if (!InitQCLib())
            {
                return;
            }
            OnAppStartupFinished();
            StartServer();
            Close();
        }

        public static void StartServer()
        {
            _processor = new QCProcess();
            _server = new CardPhotoQCServer("qc_pipe");
            _server.Checking += _processor.OnHandling;
            _processor.AppExited += _server.Stop;
            _processor.Init();
            _server.Start();
        }

        private static bool InitQCLib()
        {
            QCFactory = QCProductFactory.Instance;
            QCOptions QCOpts = (QCOptions)(Configs.QC.Clone() as QCOptions);
            bool bNeedInit = false;
            if (Configs.TakingOption.ServiceType == ServiceTypes.ExitAndEntry
                || Configs.TakingOption.ServiceType == ServiceTypes.Optional
                || Configs.TakingOption.ServiceType == ServiceTypes.PassportAndVisa)
            {
                if (Configs.QC.CRJ.Enabled)
                {
                    bNeedInit = true;
                }
            }
            if (Configs.TakingOption.ServiceType == ServiceTypes.PortVisa
                || Configs.TakingOption.ServiceType == ServiceTypes.PassportAndVisa)
            {
                if (Configs.QC.Visa.Enabled)
                {
                    bNeedInit = true;
                }
            }
            if (bNeedInit)
            {
                bool bRet = QCFactory.InitQCLib(QCOpts);
                if (bRet)
                {
                    _bInitQCLib = true;
                    Log.WriteAsync("一所动态库初始化成功.");
                }
                else
                {
                    Log.WriteAsync(QCFactory.Error);
                }
                return bRet;
            }
            return true;
        }

        private static void ExitQCLib()
        {
            if (!_bInitQCLib || QCFactory == null)
            {
                return;
            }
            QCFactory.Dispose();
        }

        /// <summary>
        /// 通知主窗体该进程启动已经完成
        /// </summary>
        protected static void OnAppStartupFinished(int code = 1, string msg = "程序加载成功")
        {
            // 当父窗体为空时，不需要通知
            if (IntPtr.Zero == ParentFormHandle || _bNotified)
            {
                Log.WriteAsync(string.Format("{0}获取父进程主窗口句柄为空，不启用进程监测.", AppName));
                return;
            }
            string sendMsg = string.Format("{0}#{1}#{2}", AppName, code, msg);
            Pipe t = new Pipe(11, sendMsg, "MainStartup");
            Task.Factory.StartNew(new Action(t.run));
            Log.WriteAsync("已经通知主窗体启动完成: " + AppName);
            _bNotified = true;
        }

        private static void LoadConfig()
        {
            ConfigService service = ConfigService.GetInstance();
            service.LoadConfig();
            if (!service.CheckLoadAllSuccess())
            {
                string[] errArray = service.GetLoadErrors();
                string title = "部分参数加载异常，详细异常信息如下:";
                Log.WriteAsync(title);
                foreach (string info in errArray)
                {
                    Log.WriteAsync(info);
                }
            }
        }

        public static void Close()
        {
            if (_bInitQCLib)
            {
                ExitQCLib();
                _processor.Exit();
            }
        }

        public static void TraceWorkingState(string info)
        {
            string timeStamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ffffff");
            Console.WriteLine(timeStamp + "\t" + info);
        }

        #region Handle the Close Event

        [DllImport("kernel32.dll")]
        private static extern bool SetConsoleCtrlHandler(ControlCtrlDelegate HandlerRoutine, bool Add);

        public static ControlCtrlDelegate newDelegate = new ControlCtrlDelegate(HandlerRoutine);

        public static bool HandlerRoutine(int CtrlType)
        {
            switch (CtrlType)
            {
                case 0:
                    Console.WriteLine("0工具被强制关闭"); //Ctrl+C关闭  
                    //相关代码执行
                    break;
                case 2:
                    Console.WriteLine("2工具被强制关闭");//按控制台关闭按钮关闭 
                    //相关代码执行 
                    Close();
                    break;
            }
            return false;
        }
        #endregion

        #region Windows API
        [DllImport("User32.dll", EntryPoint = "FindWindow")]
        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll", EntryPoint = "FindWindowEx")]   //找子窗体   
        private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

        [DllImport("User32.dll", EntryPoint = "SendMessage")]   //用于发送信息给窗体   
        private static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, string lParam);

        [DllImport("User32.dll", EntryPoint = "ShowWindow")]   //
        private static extern bool ShowWindow(IntPtr hWnd, int type);
        #endregion
    }
}
